var goRequestHandlers;
var gbExtensionRequestDebug = false;

function backgroundRequest(sType, sValue, fSuccessCallBack, fFailureCallBack) {
  if (gbExtensionRequestDebug)
      debugLog("backgroundRequest: type=" + repr(sType) + ", value=" + repr(sValue) + ".");
  chrome.extension.sendRequest(
      {"type": sType, "value": sValue},
      function(oResult) {
        if (oResult.error) {
          debugLog("backgroundRequest: Result=error:" + repr(oResult.value));
          if (fFailureCallBack) fFailureCallBack(oResult.value);
        } else {
          if (gbExtensionRequestDebug)
              debugLog("backgroundRequest: Result=success:" + repr(oResult.value));
          if (fSuccessCallBack) fSuccessCallBack(oResult.value);
        }
      }
  );
}

function tabRequest(iTabId, sType, sValue, fSuccessCallBack, fFailureCallBack) {
  if (gbExtensionRequestDebug)
      debugLog("tabRequest: tab=" + repr(iTabId) + ", type=" + repr(sType) + ", value=" + repr(sValue) + ".");
  chrome.tabs.sendRequest(
      iTabId,
      {"type": sType, "value": sValue},
      function(oResult) {
        if (oResult.error) {
          debugLog("tabRequest: Result=error:" + repr(oResult.value));
          if (fFailureCallBack) fFailureCallBack(oResult.value);
        } else {
          if (gbExtensionRequestDebug)
              debugLog("tabRequest: Result=success:" + repr(oResult.value));
          if (fSuccessCallBack) fSuccessCallBack(oResult.value);
        }
      }
  );
}

function addRequestHandler(sRequestName, fHandler) {
  if (!goRequestHandlers) {
    if (gbExtensionRequestDebug)
        debugLog("addRequestHandler: Installing request listener...");
    chrome.extension.onRequest.addListener(__requestHandler);
    goRequestHandlers = {};
  } else {
    assert(!goRequestHandlers[sRequestName],
        "A handler for request " + repr(sRequestName) + " has already been installed.");
  }
  if (gbExtensionRequestDebug)
      debugLog("addRequestHandler: Request handler for " + repr(sRequestName) + " installed.");
  goRequestHandlers[sRequestName] = fHandler;
}

function __requestHandler(oRequest, oSender, fSendResponse) {
  if (oSender.tab) {
    var sSender = "tab #" + oSender.tab.id;
  } else {
    var sSender = "background page";
  }
  if (!goRequestHandlers[oRequest.type]) {
    debugLog("requesthandler: Received unhandled request from " + sSender + ": " + repr(oRequest));
    fSendResponse({"error": true, "value": "No request handler registered for " + repr(oRequest.type)});
  } else {
    if (gbExtensionRequestDebug)
        debugLog("requesthandler: Handling request received from " + sSender + ": " + repr(oRequest));
    try {
      goRequestHandlers[oRequest.type](
          oRequest.value,
          oSender,
          function (oResult) {
            if (gbExtensionRequestDebug)
                debugLog("requesthandler: Request handler report success: " + repr(oResult));
            fSendResponse({"error": false, "value": oResult});
          },
          function (sErrorMessage) {
            debugLog("requesthandler: Request handler report an error: " + repr(sErrorMessage));
            fSendResponse({"error": true, "value": sErrorMessage});
          }
      );
    } catch (e) {
      debugLog("Exception in request handling code\r\n" + e.message + "\r\n" + e.stack);
      fSendResponse({"error": true, "value": "Exception handling request: " + e.message});
    }
  }
}
